<template>
  <div>
    <span @click="onShowDrawer">
      <slot></slot>
    </span>

    <h-drawer v-model="visible" :loading="loading" :width="1200" unit="px">
      <template #title>
        <span v-if="props.workNo" style="font-size: 16px">审核费用</span>
        <span v-else class="add_fee_title">
          <span>新增服务项目</span>
        </span>
      </template>
      <div class="body">
        <div v-if="props.workNo" class="info-list">
          <div class="info-item">
            <div class="label">工单单号:</div>
            <div class="value">{{ props.workNo }}</div>
          </div>
          <div class="info-item">
            <div class="label">审核状态:</div>
            <div class="value">
              <HStatus :height="22" type="warning">待审核</HStatus>
            </div>
          </div>
          <div class="info-item">
            <div class="label">审核备注:</div>
            <div class="value">
              <el-input
                  v-model.trim="auditRemark"
                  clearable
                  maxlength="200"
                  placeholder="填写备注信息"
                  resize="both"
                  show-word-limit
                  size="small"
                  type="textarea"
              />
            </div>
          </div>
        </div>
        <el-table
            :border="true"
            :data="feeList"
            :max-height="700"
            :span-method="cellMerge"
            resizable
        >
          <!-- 序号 -->
          <el-table-column :align="'center'" fixed="left" label="序号" type="index" width="50"/>

          <!-- 费用单号 -->
          <el-table-column v-if="props.workNo" label="费用单号" prop="feeNo" width="150"/>

          <!-- 收支类型 -->
          <el-table-column label="结算类型" width="150">
            <template #default="{ row, $index }">
              <el-select
                  v-model="row.type"
                  filterable
                  placeholder="结算类型"
                  @change="onChangeIncomeOrPayType($index)"
              >
                <el-option :value="1" label="公司承担"></el-option>
                <el-option :value="2" label="收取客户"></el-option>
                <el-option :value="3" label="支付部门"></el-option>
              </el-select>
            </template>
          </el-table-column>

          <!-- 费用名称 -->
          <el-table-column label="费用名称" show-overflow-tooltip width="150">
            <template #default="{ row, $index }">
              <el-select
                  v-model="row.workFeeProjectId"
                  :class="{
                  'validate-fail-select': isEnableTableValidate && !row.workFeeProjectId,
                }"
                  :filter-method="handleGetFeeProjectOptions"
                  :loading="getFeePorjectOptionListLoading"
                  filterable
                  placeholder="请选择"
                  remote-show-suffix
              >
                <el-option
                    v-for="item in feeProjectOptionList"
                    :key="item.name"
                    :label="item.name"
                    :value="item.id"
                    @click="handleChangeFeeProject(item, $index)"
                />
              </el-select>
            </template>
          </el-table-column>

          <!-- 公里数 -->
          <el-table-column label="公里数" show-overflow-tooltip width="160">
            <template #default="{ row, $index }">
              <el-input-number
                  v-model.trim="row.kilometers"
                  :controls="false"
                  :disabled="!getIsEnableKilometer(row.workFeeProjectId)"
                  :max="999"
                  :min="0"
                  placeholder="请输入公里数"
                  style="width: 120px"
                  @change="handleSilometerChange($index)"
              />
            </template>
          </el-table-column>

          <!-- 申请数量 -->
          <el-table-column label="申请数量" show-overflow-tooltip width="160">
            <template #default="{ row, $index }">
              <el-input-number
                  v-model.trim="row.qty"
                  :controls="false"
                  :max="999"
                  :min="1"
                  placeholder="请输入数量"
                  style="width: 120px"
                  @change="handleQtyChange($index)"
              />
            </template>
          </el-table-column>

          <!-- 公司承担 -->
          <el-table-column label="公司承担费用" width="180">
            <template #default="{ row, $index }">
              <el-input-number
                  v-model.trim="row.price"
                  :controls="false"
                  :max="9999.99"
                  :min="0"
                  clearable
                  placeholder="请输入公司承担费用"
                  style="width: 140px"
                  @change="handleFeeChange($index, 'price')"
              />
            </template>
          </el-table-column>

          <!-- 客户承担 -->
          <el-table-column label="收取客户费用" width="180">
            <template #default="{ row, $index }">
              <el-input-number
                  v-model.trim="row.customerUndertakePrice"
                  :controls="false"
                  :max="9999.99"
                  :min="0"
                  clearable
                  placeholder="请输入收取客户费用"
                  style="width: 140px"
                  @change="handleFeeChange($index, 'customerUndertakePrice')"
              />
            </template>
          </el-table-column>

          <!-- 部门承担 -->
          <el-table-column label="支付部门费用" width="180">
            <template #default="{ row, $index }">
              <el-input-number
                  v-model.trim="row.networkUndertakePrice"
                  :controls="false"
                  :max="9999.99"
                  :min="0"
                  clearable
                  placeholder="请输入支付部门费用"
                  style="width: 140px"
                  @change="handleFeeChange($index, 'networkUndertakePrice')"
              />
            </template>
          </el-table-column>

          <!-- 备注 -->
          <el-table-column label="备注" show-overflow-tooltip width="240">
            <template #default="{ row }">
              <el-input
                  v-model.trim="row.remark"
                  clearable
                  maxlength="100"
                  placeholder="填写备注"
              />
            </template>
          </el-table-column>

          <!-- 附件 -->
          <el-table-column :width="annexColumnWidth" label="附件(最多上传8个)">
            <template #default="{ row, $index }">
              <div class="updata_pic">
                <template v-for="(img, index) in row.images" :key="index">
                  <h-image
                      :height="37.5"
                      :initial-index="index"
                      :mask-btn-gap="3"
                      :padding="2"
                      :preview-src-list="row.images.map((item) => item.image)"
                      :show-del-btn="!img.id"
                      :src="img.image"
                      :width="60"
                      fit="scale-down"
                      @del="handleDelFile($index, index)"
                  />
                </template>
                <h-image
                    v-if="row.images.length < 8"
                    :height="37.5"
                    :padding="2"
                    :src="uploadPlaceholderImg"
                    :width="60"
                >
                  <el-upload
                      :auto-upload="false"
                      :on-change="(file: UploadFile) => handleAddFile(file, $index)"
                      :show-file-list="false"
                      accept="image/*"
                      action="#"
                      multiple
                  >
                    <i class="iconfont icon-img-upload" style="font-size: 24px; color: #fff"></i>
                  </el-upload>
                </h-image>
              </div>
            </template>
          </el-table-column>

          <!--审核状态-->
          <el-table-column
              v-if="props.workNo"
              :align="'center'"
              fixed="right"
              label="审核"
              width="120"
          >
            <template #default="{ row }">
              <el-select v-model="row.status" filterable placeholder="审核状态">
                <el-option :value="2" label="通过"></el-option>
                <el-option :value="3" label="驳回"></el-option>
              </el-select>
            </template>
          </el-table-column>

          <el-table-column v-if="!props.workNo" fixed="right" label="操作" width="100">
            <template #default="{ row, $index }">
              <el-space :size="0" :spacer="spacer">
                <h-link
                    v-if="!row.feeDetailId && feeList.length > 1"
                    type="error"
                    @click="onDelFeeDetail($index)"
                >删除
                </h-link
                >
                <h-link v-if="$index === 0" @click="onAddFeeDetail">添加</h-link>
              </el-space>
            </template>
          </el-table-column>
        </el-table>
      </div>

      <template #footer>
        <HButton is-modal type="primary" @click="onSave">保存</HButton>
        <HButton is-modal @click="onClose">取消</HButton>
      </template>
    </h-drawer>
  </div>
</template>

<script lang="ts" setup>
import {computed, h, ref} from 'vue'
import {orderAnnexUpload} from '@/api/upload'
import {ElDivider, ElUpload, UploadFile} from 'element-plus'
import _ from 'lodash'
import uploadPlaceholderImg from '@/assets/image/avatar_upload_default.png'
import {HMessage, HMessageBox} from '@/components/common/message'
import {
  useFeeCreate,
  useFeeMultipleCheck,
  useGetFeeByOrderId,
  useGetFeePorjectOptionList,
} from '@/services/pages/order/useOrderDetail'
import {CellMergeParam, Fee} from './types'

const {
  checkForm: multipleCheckForm,
  checkLoading: multipleCheckLoading,
  check: multipleCheck,
} = useFeeMultipleCheck()
const {feeList: feeListByOrderId, getFeeLoading, getFee: getFeeById} = useGetFeeByOrderId()
const {createForm, createLoading, create} = useFeeCreate()
const {
  optionList: feeProjectOptionList,
  getOptionListParam: getFeePorjectOptionListParam,
  getOptionListLoading: getFeePorjectOptionListLoading,
  getOptionList: getFeePorjectOptionList,
} = useGetFeePorjectOptionList()

// 如果有传workId就是审核费用，否则就是申请费用
const props = defineProps({
  workId: {
    type: String,
    default: () => '',
  },
  workNo: {
    type: String,
    default: () => '',
  },
})

const emits = defineEmits<{
  (e: 'update'): void
}>()

// 审核备注
const auditRemark = ref('')

// 间距组件的间隔符
const spacer = h(ElDivider, {
  direction: 'vertical',
  style: 'display: flex; align-items: center;',
})

// 是否开启表格检查
const isEnableTableValidate = ref(false)

// 加载
const loading = computed(() => {
  return (
      getFeeLoading.value ||
      multipleCheckLoading.value ||
      createLoading.value ||
      fileUploadLoading.value
  )
})

// 添加费用弹窗显示状态
const visible = ref(false)

// 费用列表
const feeList = ref<Array<Fee>>([])

// 文件上传加载
const fileUploadLoading = ref(false)

// 附件列宽
const annexColumnWidth = ref(160)

/**
 * 单元格合并
 */
const cellMerge = ({row, columnIndex}: CellMergeParam) => {
  if (columnIndex === 1 && props.workNo) {
    const _feeList = feeList.value.filter((item) => item.feeId === row.feeId)
    const index = _feeList.findIndex((item) => item.feeDetailId === row.feeDetailId)
    if (index === 0) {
      return {
        rowspan: _feeList.length,
        colspan: 1,
      }
    } else {
      return {
        rowspan: 0,
        colspan: 0,
      }
    }
  }
}

/**
 * 设置附件列的宽度
 */
const setAnnexColumnWidth = () => {
  let maxImageLength = Math.max(...feeList.value.map((item) => item.images.length))

  // 在图片数量小于8张时要把上传按钮的宽度计算进去
  if (maxImageLength < 8) {
    maxImageLength += 1
  }

  // 这是为了解决删剩一张图时，列宽会变得很小，导致标题会换行
  if (maxImageLength > 0) {
    annexColumnWidth.value = maxImageLength * 60 + (maxImageLength - 1) * 8 + 24
  }

  if (annexColumnWidth.value < 130) {
    annexColumnWidth.value = 130
  }
}

/**
 * 添加费用详情
 */
function onAddFeeDetail() {
  feeList.value.push({
    delImageIds: [],
    feeId: '',
    images: [],
    networkUndertakePrice: 0,
    price: 0,
    qty: 1,
    customerUndertakePrice: 0,
    remark: '',
    type: 1,
    workFeeProjectId: '',
    kilometers: 0,
    status: 2,
    feeNo: '',
    orderId: props.workId,
    feeDetailId: '',
  })
}

/**
 * 费用详情删除
 * @param index - 费用索引
 */
function onDelFeeDetail(index: number) {
  if (feeList.value.length === 1) {
    return
  }
  feeList.value.splice(index, 1)
}

/**
 * 保存按钮点击事件
 */
const onSave = async () => {
  isEnableTableValidate.value = true
  if (props.workNo) {
    const feeTempObj: Record<string, Array<Fee>> = {}

    for (let i = 0; i < feeList.value.length; i++) {
      const fee = feeList.value[i]
      if (Object.keys(feeTempObj).includes(fee.feeId)) {
        feeTempObj[fee.feeId].push(fee)
      } else {
        feeTempObj[fee.feeId] = [fee]
      }

      if (!fee.workFeeProjectId) {
        HMessageBox.error('请选择费用名称')
        return
      }

      const files = fee.images.filter((item) => !!item.file).map((item) => item.file)
      if (files.length > 0) {
        const res = await orderAnnexUpload(files)
        feeList.value[i].images = feeList.value[i].images.filter((item) => !!item.id)
        res.data.data.rows.forEach((imgUrl) => {
          feeList.value[i].images.push({
            id: null,
            image: imgUrl,
          })
        })
      }
    }

    for (const key in feeTempObj) {
      const fee = feeTempObj[key]
      multipleCheckForm.value.checkVoList.push({
        id: fee[0].feeId,
        remark: auditRemark.value,
        feeDetails: fee.map((item) => {
          return {
            customerUndertakePrice: item.customerUndertakePrice,
            delImageIds: item.delImageIds,
            id: item.feeDetailId,
            images: item.images.map((imgRow) => {
              return {
                id: imgRow.id,
                image: imgRow.image,
              }
            }),
            kilometers: item.kilometers,
            networkUndertakePrice: item.networkUndertakePrice,
            price: item.price,
            qty: item.qty,
            remark: item.remark,
            status: item.status,
            type: item.type,
            workFeeProjectId: item.workFeeProjectId,
          }
        }),
      })
    }

    const res = await multipleCheck()
    if (res.code === 20000) {
      HMessage.success('保存成功')
      emits('update')
      visible.value = false
      feeList.value.length = 0
      return
    }
    HMessageBox.error(res.message)
  } else {
    // 创建
    createForm.value = {
      delFeeDetailIds: [],
      feeDetails: feeList.value.map((item) => {
        return {
          customerUndertakePrice: item.customerUndertakePrice,
          delImageIds: item.delImageIds,
          id: item.feeDetailId,
          images: item.images.map((imgRow) => {
            return {
              id: imgRow.id,
              image: imgRow.image,
            }
          }),
          kilometers: item.kilometers,
          networkUndertakePrice: item.networkUndertakePrice,
          price: item.price,
          qty: item.qty,
          remark: item.remark,
          status: item.status,
          type: item.type,
          workFeeProjectId: item.workFeeProjectId,
        }
      }),
      id: '',
      remark: auditRemark.value,
      workId: props.workId,
    }
    const res = await create()
    if (res.code === 20000) {
      HMessage.success('保存成功')
      emits('update')
      visible.value = false
      feeList.value.length = 0
      return
    }
    HMessageBox.error(res.message)
  }
}

/**
 * 费用项目选择事件
 * @param {Object} item - 费用项目
 * @param index - 费用索引
 */
function handleChangeFeeProject(item: OrderFeeProjectOption, index: number) {
  feeList.value[index].customerUndertakePrice = 0
  feeList.value[index].price = 0
  feeList.value[index].networkUndertakePrice = 0
  switch (feeList.value[index].type) {
    case 1:
      feeList.value[index].price = item.price
      break
    case 2:
      feeList.value[index].customerUndertakePrice = item.price
      break
    case 3:
      feeList.value[index].networkUndertakePrice = item.price
      break
  }
}

/**
 * 费用项目下拉数据
 */
const handleGetFeeProjectOptions = _.throttle((query: string) => {
  if (getFeePorjectOptionListParam.value.name !== query) {
    getFeePorjectOptionListParam.value.name = query
    getFeePorjectOptionList()
  }
}, 600)

/**
 * 添加图片或pdf
 * @param file - 文件
 * @param index - 费用索引
 */
const handleAddFile = async (file: UploadFile, index: number) => {
  if (!file.raw) {
    return false
  }

  if (!file.raw.type.includes('image')) {
    HMessageBox.error('只能上传图片类型的文件')
    return
  }
  if (feeList.value[index].images.length >= 8) {
    HMessageBox.error('上传的数量不能超过8个')
    return
  }
  feeList.value[index].images.push({
    file: file.raw,
    image: URL.createObjectURL(file.raw),
    id: '',
  })
  setAnnexColumnWidth()
}

/**
 * 删除文件
 * @param index - 费用索引
 * @param imgIndex - 文件索引
 */
const handleDelFile = (index: number, imgIndex: number) => {
  if (feeList.value[index].images[imgIndex].id) {
    HMessageBox.error('禁止删除原本附件')
    return
  }
  const imgs = feeList.value[index].images.splice(imgIndex, 1)
  feeList.value[index].delImageIds.push(imgs[0].id)
  setAnnexColumnWidth()
}

/**
 * 显示申请费用弹窗
 */
const onShowDrawer = async () => {
  visible.value = true
  getFeePorjectOptionList()
  if (props.workNo) {
    // 批量审核
    await getFeeById(props.workId)
    feeList.value.length = 0
    feeListByOrderId.value.forEach((fee) => {
      fee.feeDetailInfoVos.forEach((feeDetail) => {
        feeList.value.push({
          orderId: props.workId,
          feeId: fee.id,
          delImageIds: [],
          feeDetailId: feeDetail.id,
          images: feeDetail.images.map((img) => {
            return {
              id: img.id,
              image: img.image,
              file: null,
            }
          }),
          networkUndertakePrice: feeDetail.networkUndertakePrice,
          price: feeDetail.price,
          qty: feeDetail.qty,
          customerUndertakePrice: feeDetail.customerUndertakePrice,
          remark: feeDetail.remark,
          type: feeDetail.type,
          workFeeProjectId: feeDetail.workFeeProjectId,
          kilometers: feeDetail.kilometers,
          status: feeDetail.status === 2 || feeDetail.status === 3 ? feeDetail.status : 2,
          feeNo: fee.workFeeNo,
        })
      })
    })
  } else {
    // 创建
    feeList.value = [
      {
        orderId: props.workId,
        feeId: '',
        remark: '',
        delImageIds: [],
        feeDetailId: '',
        images: [],
        networkUndertakePrice: 0,
        price: 0,
        customerUndertakePrice: 0,
        qty: 1,
        kilometers: 0,
        type: 1,
        status: 2,
        workFeeProjectId: '',
        feeNo: '',
      },
    ]
  }

  setAnnexColumnWidth()
}

/**
 * 收支类型改变
 * @param index - 费用索引
 */
const onChangeIncomeOrPayType = (index: number) => {
  // 提取费用项目的金额
  let price = 0
  const feeDetail = feeList.value[index]
  if (feeDetail.workFeeProjectId) {
    const feeProject = feeProjectOptionList.value.find(
        (feeProject) => feeProject.id === feeDetail.workFeeProjectId,
    )
    if (feeProject) {
      price = feeProject.price
    }
  }
  feeList.value[index].customerUndertakePrice = 0
  feeList.value[index].price = 0
  feeList.value[index].networkUndertakePrice = 0
  switch (feeDetail.type) {
    case 1:
      feeList.value[index].price = price
      break
    case 2:
      feeList.value[index].customerUndertakePrice = price
      break
    case 3:
      feeList.value[index].networkUndertakePrice = price
      break
  }
}

/**
 * 关闭事件
 */
const onClose = () => {
  feeList.value.length = 0
  visible.value = false
}

/**
 * 根据费用id获取费用使用开启公里数
 */
const getIsEnableKilometer = (feeId: string) => {
  const fee = feeProjectOptionList.value.find((feeProject) => feeProject.id === feeId)
  if (!fee) {
    return false
  }
  return fee.enableRemoteFees
}

/**
 * 公里数更新事件
 * @param index - 费用索引
 */
const handleSilometerChange = (index: number) => {
  const feeDetail = feeList.value[index]
  if (['undefined', 'null', ''].includes(`${feeDetail.kilometers}`.trim())) {
    feeList.value[index].kilometers = 0
  }

  const feeProject = feeProjectOptionList.value.find(
      (item) => item.id === feeDetail.workFeeProjectId,
  )

  if (feeProject && feeProject.enableRemoteFees && !(feeDetail.networkUndertakePrice > 0)) {
    if (feeDetail.kilometers > 20) {
      feeDetail.networkUndertakePrice = (feeDetail.kilometers - 20) * 1.2
    }
  }
}

/**
 * 数量更新事件
 * @param index - 费用索引
 */
const handleQtyChange = (index: number) => {
  const feeDetail = feeList.value[index]
  if (['undefined', 'null', ''].includes(`${feeDetail.qty}`.trim())) {
    feeList.value[index].qty = 1
  }
}

/**
 * (公司承担、收取客户、支付部门)费用更新事件
 * @param index - 费用索引
 * @param type - price(公司承担)、customerUndertakePrice(收取客户)、networkUndertakePrice(支付部门)
 */
const handleFeeChange = (
    index: number,
    type: 'price' | 'customerUndertakePrice' | 'networkUndertakePrice',
) => {
  const feeDetail = feeList.value[index]
  if (['undefined', 'null', ''].includes(`${feeDetail[type]}`.trim())) {
    feeList.value[index][type] = 0
  }
}
</script>

<style lang="scss" scoped>
:deep(.el-select__wrapper) {
  min-height: 28px !important;
  border-radius: 2px !important;
  font-size: 12px !important;
}

:deep(.el-input__wrapper) {
  height: 28px !important;
  font-size: 12px !important;
}

:deep(.el-table td.el-table__cell) {
  .el-input {
    .el-input-group__prepend {
      padding: 0 2px;
    }
  }
}

:deep(.el-input-number) {
  .el-input {
    .el-input__wrapper {
      .el-input__inner {
        text-align: left;
      }
    }
  }
}

.validate-fail-select {
  :deep(.el-select__wrapper) {
    box-shadow: 0 0 0 1px $deleteColor inset;
  }
}

.add_fee_title {
  display: flex;
  align-items: center;
  gap: 5px;
}

.body {
  display: flex;
  flex-direction: column;
  row-gap: 12px;
  height: 100%;

  .info-list {
    display: flex;
    column-gap: 12px;

    .info-item {
      display: flex;
      column-gap: 4px;
      align-items: center;

      .label {
        color: #606266;
      }

      .value {
        :deep(.el-textarea) {
          .el-textarea__inner {
            height: 28px;
            min-height: 28px !important;
            width: 400px !important;
            max-height: 140px !important;
          }
        }
      }
    }
  }
}

.fee-item {
  display: flex;
  flex-direction: column;

  .check_header_info_list {
    display: flex;
    column-gap: 72px;
    row-gap: 12px;
    padding-bottom: 6px;
    flex-wrap: wrap;

    .info_item {
      display: flex;
      gap: 5px;
      align-items: flex-start;

      .label {
        color: #606266;
        height: 28px;
        line-height: 28px;
      }

      .value {
        min-height: 28px;
        display: flex;
        align-items: center;

        :deep(.el-textarea) {
          .el-textarea__inner {
            min-height: 28px !important;
            height: 28px;
            max-height: 100px !important;
            min-width: 205px !important;
            max-width: 560px !important;
          }
        }
      }
    }
  }
}

:deep(.updata_pic) {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 40px;

  .el-upload {
    &.el-upload--picture-card {
      width: 40px;
      height: 40px;
    }
  }

  .disf_ipc {
    display: flex;
    width: 40px;
    height: 40px;
    position: relative;
    margin-right: 6px;
    border: 1px solid #7f7f7f27;
    border-radius: 2px;
    box-sizing: border-box;
    overflow: hidden;

    .img {
      width: 100%;
      position: absolute;
      border-radius: 2px;
    }

    .item-actions {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      z-index: 1;
      opacity: 0;
    }

    &:hover .item-actions {
      display: flex;
      align-items: center;
      justify-content: center;
      background-color: #7f7f7f9d;
      opacity: 1;
      border-radius: 2px;

      .item-preview {
        margin: 0 4px;
        cursor: pointer;

        &:hover {
          transform: scale(1.2);
        }
      }

      .item-delete {
        margin: 0 4px;
        cursor: pointer;

        &:hover {
          transform: scale(1.2);
        }
      }
    }
  }
}

</style>
